﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using MSBTC.Model;

namespace MSBTC.WinForms
{
    public partial class AssignMtrlForm : Form
    {
        PMSContext dbcontext = new PMSContext();
        MaterialsInventory dbeqp = new MaterialsInventory();
        ProjMat dbpjmat = new ProjMat();
        private int[] numitemselcted = new int[1000];
        private string[] itemselected = new string[1000];
        private string[] retequip = new string[1000];
        private int[] qtyret = new int[1000];

        public AssignMtrlForm()
        {
            InitializeComponent();
        }

        private void AssignMtrlForm_Load(object sender, EventArgs e)
        {
            cmbPName.SelectedIndex = 0;
            txtqty.Enabled = false;
            lbMat.Enabled = false;
            lblsct.Enabled = false;
            btnfront.Enabled = false;
            btnBack.Enabled = false;
            btnSave.Enabled = false;

            Array.Clear(numitemselcted, 0, numitemselcted.Length);
            Array.Clear(itemselected, 0, itemselected.Length);
            Array.Clear(retequip, 0, retequip.Length);
            Array.Clear(qtyret, 0, qtyret.Length);

            var name = (from p in dbcontext.Projects
                        select p).ToList();
            if (name != null)
            {
                foreach (var pn in name)
                {
                    cmbPName.Items.Add(pn.Project_Name);
                }
            }
            else
            {
                MessageBox.Show("There are no Projects listed, please add new projects in main menu.", "Data Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                cmbPName.SelectedIndex = 0;
                this.Hide();
            }

            var eqmt = (from eq in dbcontext.MaterialsInventorys
                        where eq.Qty - eq.QtyUsed != 0
                        select eq).ToList();
            if (eqmt != null)
            {
                foreach (var eqp in eqmt)
                {
                    lbMat.Items.Add(eqp.Material_Name);
                }
            }
            else
            {
                MessageBox.Show("There are no Materials stored, please add new Materials in main menu", "Data Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                this.Hide();
            }
        }

        private void cmbPName_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            lblsct.Items.Clear();
            lblQty.Text = "";
            txtqty.Clear();
            lblused.Text = "";
            lbltrans.Text = "";
            if (cmbPName.SelectedIndex != 0)
            {
                Array.Clear(numitemselcted, 0, numitemselcted.Length);
                Array.Clear(itemselected, 0, itemselected.Length);
                Array.Clear(retequip, 0, retequip.Length);
                Array.Clear(qtyret, 0, qtyret.Length);

                lbMat.Enabled = true;
                lblsct.Enabled = true;
                btnfront.Enabled = true;
                btnBack.Enabled = true;
                btnSave.Enabled = true;

                var prj = (from eq in dbcontext.Projects
                           where eq.Project_Name == cmbPName.SelectedItem
                           select eq).SingleOrDefault();
                if (prj != null)
                {
                    var prjmat = (from pe in dbcontext.PrjMatls
                                 where pe.Projectid_FK == prj.Projectid_PK
                                 select pe).ToList();
                    if (prjmat != null)
                    {
                        foreach (var peq in prjmat)
                        {
                            var eqmt = dbcontext.MaterialsInventorys.Find(peq.MaterialsInventoryid_FK);
                            lblsct.Items.Add(eqmt.Material_Name);
                        }
                    }
                }
            }
        }

        private void lbMat_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            lblQty.Text = "";
            lblused.Text = "";
            btnBack.Enabled = false;
            btnfront.Enabled = true;

            if (lblsct.SelectedIndex != -1)
            {
                lblsct.ClearSelected();
                //lblsct.SelectedIndex = 0;

            }
            if (lbMat.SelectedItems.Count != 0)
            {
                txtqty.Enabled = true;
                string itmslt = lbMat.SelectedItem.ToString();
                var matl = (from mat in dbcontext.MaterialsInventorys
                          where mat.Material_Name == itmslt
                          select mat).SingleOrDefault();
                if (matl != null)
                {
                    //var proj = (from p in dbcontext.Projects
                    //            where p.Project_Name == cmbPName.SelectedItem
                    //            select p).SingleOrDefault();

                    //var pmat = (from pj in dbcontext.PrjMatls
                    //            where pj.MaterialsInventoryid_FK == matl.MaterialsInventoryid_PK && pj.Projectid_FK == proj.Projectid_PK
                    //            select pj).SingleOrDefault();
                    //if (pmat != null)
                    //{
                        lblQty.Text = Convert.ToString(matl.Qty - matl.QtyUsed);
                        lblused.Text = matl.QtyUsed.ToString();
                    //}
                }

                int indx = Array.IndexOf(itemselected, itmslt);
                if (indx != -1)
                {
                    lbltrans.Text = numitemselcted[indx].ToString();
                }
                else
                {
                    lbltrans.Text = "0";
                }
            }
            else
            {
                lblsct.SelectedItem = -1;
                txtqty.Enabled = false;
            }
        }

        private void lblsct_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            lblQty.Text = "";
            btnfront.Enabled = false;
            btnBack.Enabled = true;

            if (lbMat.SelectedIndex != -1)
            {
                lbMat.ClearSelected();
                //lbEquip.SelectedIndex = 0;
            }
            if (lblsct.SelectedItems.Count != 0)
            {
                txtqty.Enabled = true;
                string itmslt = lblsct.SelectedItem.ToString();
                List<string> itmlst = new List<string>(retequip);
                List<int> qtylst = new List<int>(numitemselcted);

                var proj = (from p in dbcontext.Projects
                            where p.Project_Name == cmbPName.SelectedItem
                            select p).SingleOrDefault();

                var mts = (from Mat in dbcontext.MaterialsInventorys
                          where Mat.Material_Name == itmslt
                          select Mat).SingleOrDefault();
                if (mts != null)
                {
                    var preq = (from pj in dbcontext.PrjMatls
                                where pj.MaterialsInventoryid_FK == mts.MaterialsInventoryid_PK
                                && pj.Projectid_FK == proj.Projectid_PK
                                select pj).SingleOrDefault();

                    int qtynum = Array.IndexOf(retequip, itmslt);
                    if (qtynum != -1)
                    {
                        int addqty = qtyret[qtynum];
                        lblused.Text = preq.QtyUsed.ToString();
                        lblQty.Text = mts.Qty.ToString();
                        lbltrans.Text = addqty.ToString();
                    }
                    else
                    {
                        lblQty.Text = Convert.ToString((mts.Qty - mts.QtyUsed));
                        lblused.Text = preq.QtyUsed.ToString();
                    }
                }
                int indx = Array.IndexOf(retequip, itmslt);
                if (indx != -1)
                {
                    lbltrans.Text = qtyret[indx].ToString();
                }
                else
                {
                    lbltrans.Text = "0";
                }
            }
            else
            {
                lbMat.SelectedItem = -1;
                txtqty.Enabled = false;
            }
        }

        private void txtqty_TextChanged(object sender, System.EventArgs e)
        {
            FormHelpers help = new FormHelpers();
            //check every letters
            if (txtqty.Text != "")
            {
                if (help.SpecChar(txtqty.Text, txtqty) == false || (System.Text.RegularExpressions.Regex.IsMatch(txtqty.Text, "[^0-9]") == true))
                {
                    MessageBox.Show("Only Numeric values are allowed", "Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    txtqty.Clear();
                    return;
                }
            }
        }

        private void btnfront_Click(object sender, System.EventArgs e)
        {
            if (txtqty.Text != "")
            {
                if (Convert.ToInt32(txtqty.Text) <= Convert.ToInt32(lblQty.Text) || Convert.ToInt32(txtqty.Text) > 0)
                {
                    if (lbMat.SelectedIndex != -1)
                    {
                        string slctd = lbMat.SelectedItem.ToString();
                        int qty = Convert.ToInt32(txtqty.Text);
                        int cnt = 0;
                        if (lblsct.Items.Count != 0)
                        {
                            foreach (var item in lblsct.Items)
                            {
                                if (slctd == item)//if the selected item and item in lblsct is the same
                                {
                                    //retrieve materials to be removed in lbMat
                                    var mat = (from m in dbcontext.MaterialsInventorys
                                               where m.Material_Name == slctd //&& qty <= eq.Quantity - eq.QtyUsed
                                               select m).SingleOrDefault();
                                    if (mat != null)
                                    {
                                        //if quantity inputted was equal to the difference of 2 quantities
                                        if (qty == mat.Qty - mat.QtyUsed)
                                        { //remove the item
                                            int ans = mat.Qty - mat.QtyUsed;
                                            MessageBox.Show("The Material " + mat.Material_Name + " is at critical point of " + ans + " remaining quantity, Please order new sets of " + mat.Material_Name + " in Purchase Order", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                    
                                            lbMat.Items.Remove(slctd);
                                            break;
                                        }
                                    }
                                }//else check if not equal to selected materials and does not contains with the same matname
                                else if (slctd != item && lblsct.Items.Contains(slctd) == false)
                                {
                                    var eqp = (from eq in dbcontext.MaterialsInventorys
                                               where eq.Material_Name == slctd //&& qty <= eq.Quantity - eq.QtyUsed
                                               select eq).SingleOrDefault();
                                    if (eqp != null)
                                    {
                                        //if quantity inputted was equal to the difference of 2 quantities
                                        if (qty == eqp.Qty - eqp.QtyUsed)
                                        {
                                            int ans = eqp.Qty - eqp.QtyUsed;
                                            MessageBox.Show("The Material " + eqp.Material_Name + " is at critical point of " + ans + " remaining quantity, Please order new sets of " + eqp.Material_Name + " in Purchase Order", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                    
                                            lbMat.Items.Remove(slctd);
                                        }
                                        lblsct.Items.Add(slctd);
                                        break;
                                    }
                                }
                            }
                            //store to an array for saving
                            List<string> itmlst = new List<string>(itemselected);
                            foreach (var arrlst in itmlst)
                            {//get all values stored in the itemselected
                                if (arrlst != null)
                                {
                                    cnt += 1;
                                }
                                else
                                {
                                    if (cnt > 0)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        cnt -= 1;
                                        break;
                                    }

                                }
                            }
                            //set the array value where to store
                            itemselected[cnt + 1] = slctd;
                            numitemselcted[cnt + 1] = qty;
                            lbltrans.Text = qty.ToString();
                            txtqty.Clear();
                        }
                        else//if lbsct is not null or equal 0
                        {
                            var mat = (from m in dbcontext.MaterialsInventorys
                                       where m.Material_Name == slctd //&& qty <= eq.Quantity - eq.QtyUsed
                                       select m).SingleOrDefault();
                            if (mat != null)
                            {
                                lblsct.Items.Add(slctd);
                            }
                            List<string> itmlst = new List<string>(itemselected);
                            foreach (var arrlst in itmlst)
                            {
                                if (arrlst != null)
                                {
                                    cnt += 1;
                                }
                                else
                                {
                                    if (cnt > 0)
                                    {
                                        break;
                                    }
                                    else
                                    {
                                        cnt -= 1;
                                        break;
                                    }

                                }
                            }
                            itemselected[cnt + 1] = slctd;
                            numitemselcted[cnt + 1] = qty;
                            txtqty.Clear();
                        }

                    }
                    else
                    {
                        MessageBox.Show("Please check the Quantity if not less than 0 or greater than the remaining quantity", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }
                else
                {
                    MessageBox.Show("Please enter quantity to be transfer", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
        }

        private void btnBack_Click(object sender, System.EventArgs e)
        {
            if (txtqty.Text != "")
            {
                if (Convert.ToInt32(txtqty.Text) <= Convert.ToInt32(lblused.Text) || Convert.ToInt32(txtqty.Text) > 0)
                {
                    if (lblsct.SelectedIndex != -1)
                    {
                        string itemslt = lblsct.SelectedItem.ToString();
                        int qtyno = Convert.ToInt32(txtqty.Text);

                        List<string> itmlst = new List<string>(itemselected);
                        List<int> qtylst = new List<int>(numitemselcted);
                        List<string> reteqp = new List<string>(retequip);
                        List<int> retqtyno = new List<int>(qtyret);

                        foreach (var item in lbMat.Items)
                        {
                            if (itemslt == item)//if the selected item and item in lblsct is the same
                            {
                                //retrieve equipment to be removed in lblsct
                                var mat = (from m in dbcontext.MaterialsInventorys
                                           where m.Material_Name == itemslt && qtyno <= m.Qty - m.QtyUsed
                                           select m).SingleOrDefault();
                                if (mat != null)
                                {
                                    //if quantity inputted was equal to the difference of 2 quantities
                                    if (qtyno == mat.Qty - mat.QtyUsed)
                                    { //remove the item

                                        lblsct.Items.Remove(itemslt);
                                        break;
                                    }
                                }
                            }//else check if not equal to selected Materials and does not contains with the same Matname
                            else if (itemslt != item && lbMat.Items.Contains(itemslt) == false)
                            {
                                var mat = (from m in dbcontext.MaterialsInventorys
                                           where m.Material_Name == itemslt && qtyno <= m.Qty - m.QtyUsed
                                           select m).SingleOrDefault();
                                if (mat != null)
                                {
                                    //if quantity inputted was equal to the difference of 2 quantities
                                    if (qtyno == mat.Qty - mat.QtyUsed)
                                    {
                                        lblsct.Items.Remove(itemslt);
                                    }
                                    lbMat.Items.Add(itemslt);
                                    break;
                                }
                            }
                        }

                        //remove same identity
                        foreach (var arrlst in itmlst)
                        {//get all values stored in the itemselected then remove with the same values
                            if (arrlst != null)
                            {
                                if (arrlst == itemslt)
                                {
                                    int indxno = Array.IndexOf(itemselected, arrlst);
                                    int qytno = numitemselcted[indxno];
                                    itmlst.RemoveAt(indxno);
                                    if (qytno > Convert.ToInt32(txtqty.Text))
                                    {
                                        int cnt = 0;
                                        foreach (var retarr in retequip)
                                        {
                                            if (retarr != null)
                                            {
                                                cnt += 1;
                                            }
                                            else
                                            {
                                                if (cnt > 0)
                                                {
                                                    break;
                                                }
                                                else
                                                {
                                                    cnt -= 1;
                                                    break;
                                                }
                                            }
                                        }
                                        //set the array value where to store
                                        retequip[cnt + 1] = itemslt;
                                        qtyret[cnt + 1] = qtyno - Convert.ToInt32(txtqty.Text);
                                    }
                                    qtylst.RemoveAt(indxno);
                                    break;
                                }  
                            }
                            else
                            {
                                int cntr = 0;
                                foreach (var retarr in retequip)
                                {
                                    if (retarr != null)
                                    {
                                        cntr += 1;
                                    }
                                    else
                                    {
                                        if (cntr > 0)
                                        {
                                            break;
                                        }
                                        else
                                        {
                                            cntr -= 1;
                                            break;
                                        }
                                    }
                                }
                                retequip[cntr + 1] = itemslt;
                                qtyret[cntr + 1] = Convert.ToInt32(txtqty.Text);
                                break;
                            }
                        }
                        lbltrans.Text = txtqty.Text;
                        txtqty.Clear();
                    }
                }
                else
                {
                    MessageBox.Show("Please check the Quantity if not less than 0 or greater than the quantity used", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            else
            {
                MessageBox.Show("Please enter quantity to be transfer", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }

        private void btnSave_Click(object sender, System.EventArgs e)
        {
            List<string> reteqp = new List<string>(retequip);
            List<int> retqtyno = new List<int>(qtyret);
            int ctr = 0;

            try
            {
                foreach (var lstitm in itemselected)
                {
                    if (lstitm != null)
                    {
                        ctr += 1;
                        int eqindx = Array.IndexOf(itemselected, lstitm);
                        int qtyadd = numitemselcted[eqindx];

                        //check for existing materials for data gathering
                        var mat = (from m in dbcontext.MaterialsInventorys
                                   where m.Material_Name == lstitm
                                   select m).SingleOrDefault();
                        if (mat != null)
                        {//check for existing project name for data
                            var pj = (from p in dbcontext.Projects
                                      where p.Project_Name == cmbPName.SelectedItem
                                      select p).SingleOrDefault();
                            if (pj != null)
                            {
                                //check for existing materials in project-materials
                                var pjm = (from pm in dbcontext.PrjMatls
                                           where pm.MaterialsInventoryid_FK == mat.MaterialsInventoryid_PK && pm.Projectid_FK == pj.Projectid_PK
                                           select pm).SingleOrDefault();
                                if (pjm == null)
                                {
                                    //save new record in project-materials table
                                    dbpjmat.Projectid_FK = pj.Projectid_PK;
                                    dbpjmat.MaterialsInventoryid_FK = mat.MaterialsInventoryid_PK;
                                    dbpjmat.QtyUsed = qtyadd;
                                    dbcontext.Entry(dbpjmat).State = EntityState.Added;

                                    mat.QtyUsed += qtyadd;
                                    dbcontext.Entry(mat).State = EntityState.Modified;

                                    dbcontext.SaveChanges();

                                    //check all items in retequip array to minus all quantity with the same matname then save to database
                                    foreach (var itmlist in retequip)
                                    {
                                        if (itmlist != null)
                                        {
                                            try
                                            {
                                                var checkitm = (from eq in dbcontext.MaterialsInventorys
                                                                where eq.Material_Name == itmlist
                                                                select eq).SingleOrDefault();
                                                if (checkitm != null)
                                                {
                                                    int qtyindex = Array.IndexOf(retequip, itmlist);
                                                    int quantityno = qtyret[qtyindex];

                                                    checkitm.QtyUsed -= quantityno;
                                                    dbcontext.Entry(checkitm).State = EntityState.Modified;

                                                    var pjmats = (from pjt in dbcontext.PrjMatls
                                                                  where pjt.Projectid_FK == pj.Projectid_PK &&
                                                                  pjt.MaterialsInventoryid_FK == checkitm.MaterialsInventoryid_PK
                                                                  select pjt).SingleOrDefault();
                                                    if (pjmats != null)
                                                    {
                                                        pjmats.QtyUsed -= quantityno;
                                                        dbcontext.Entry(pjmats).State = EntityState.Modified;
                                                    }

                                                    dbcontext.SaveChanges();
                                                }
                                            }
                                            catch (Exception exc)
                                            {
                                                MessageBox.Show(exc.Message.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                                return;
                                            }
                                        }
                                    }
                                    var matr = (from m in dbcontext.MaterialsInventorys
                                                where m.Material_Name == mat.Material_Name
                                                select m).SingleOrDefault();
                                    if (matr != null)
                                    {
                                        int ans = matr.Qty - matr.QtyUsed;
                                        if (ans <= 10)
                                        {
                                            MessageBox.Show("The Material " + matr.Material_Name + " is at critical point of " + ans + " remaining quantity, Please order new sets of " + matr.Material_Name + " in Purchase Order", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                        }
                                    }
                                }
                                else
                                {
                                    //save the modified quantity used in the a particular project
                                    pjm.QtyUsed += qtyadd;
                                    dbcontext.Entry(pjm).State = EntityState.Modified;

                                    mat.QtyUsed += qtyadd;
                                    dbcontext.Entry(mat).State = EntityState.Modified;

                                    dbcontext.SaveChanges();

                                    int retitmlst = Array.IndexOf(retequip, mat.Material_Name);
                                    if (retitmlst != -1)
                                    {
                                        int quantityret = qtyret[retitmlst];
                                        mat.QtyUsed -= quantityret;
                                        dbcontext.Entry(mat).State = EntityState.Modified;

                                        pjm.QtyUsed -= quantityret;
                                        dbcontext.Entry(pjm).State = EntityState.Modified;

                                        dbcontext.SaveChanges();

                                        //int ans = mat.Qty - mat.QtyUsed;
                                        //if (ans <= 10)
                                        //{
                                        //    MessageBox.Show("The Material " + mat.Material_Name + " is at critical point of " + ans + " remaining quantity, Please order new sets of " + mat.Material_Name + " in Purchase Order", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                        //}
                                    }
                                    var matr = (from m in dbcontext.MaterialsInventorys
                                                where m.Material_Name == mat.Material_Name
                                                select m).SingleOrDefault();
                                    if (matr != null)
                                    {
                                        int ans = matr.Qty - matr.QtyUsed;
                                        if (ans <= 10)
                                        {
                                            MessageBox.Show("The Material " + matr.Material_Name + " is at critical point of " + ans + " remaining quantity, Please order new sets of " + matr.Material_Name + " in Purchase Order", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                        }

                                    }
                                }
                            }
                        }
                    }
                        else if (retequip != null)
                        {
                            try
                            {
                                foreach (var itmlist in retequip)
                                {
                                    if (itmlist != null)
                                    {

                                        var pj = (from p in dbcontext.Projects
                                                  where p.Project_Name == cmbPName.SelectedItem
                                                  select p).SingleOrDefault();
                                        if (pj != null)
                                        {
                                            var checkitm = (from eq in dbcontext.MaterialsInventorys
                                                            where eq.Material_Name == itmlist
                                                            select eq).SingleOrDefault();
                                            if (checkitm != null)
                                            {
                                                int qtyindex = Array.IndexOf(retequip, itmlist);
                                                int quantityno = qtyret[qtyindex];

                                                checkitm.QtyUsed -= quantityno;
                                                dbcontext.Entry(checkitm).State = EntityState.Modified;
                                                dbcontext.SaveChanges();

                                                var pjmats = (from pjt in dbcontext.PrjMatls
                                                              where pjt.Projectid_FK == pj.Projectid_PK &&
                                                              pjt.MaterialsInventoryid_FK == checkitm.MaterialsInventoryid_PK
                                                              select pjt).SingleOrDefault();
                                                if (pjmats != null)
                                                {
                                                    pjmats.QtyUsed -= quantityno;
                                                    dbcontext.Entry(pjmats).State = EntityState.Modified;
                                                    dbcontext.SaveChanges();
                                                }

                                            }

                                        }
                                    }
                                    else
                                    {
                                        Array.Clear(retequip, 0, retequip.Length);
                                        Array.Clear(qtyret, 0, qtyret.Length);
                                        break;
                                    }
                                }
                            }
                            catch (Exception exc)
                            {
                                MessageBox.Show(exc.Message.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                return;
                            }

                        }
                        else if (lstitm == null && ctr == 0)
                        {
                            //create code for back button to save data... RUSH!!!!
                            MessageBox.Show("There's no record to save", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            return;
                        }
                        else
                        {
                            break;
                        }
                    }
                
                MessageBox.Show("Successfully saved", "Saved", MessageBoxButtons.OK, MessageBoxIcon.Information);
                Array.Clear(numitemselcted, 0, numitemselcted.Length);
                Array.Clear(itemselected, 0, itemselected.Length);
                Array.Clear(retequip, 0, retequip.Length);
                Array.Clear(qtyret, 0, qtyret.Length);
                lbltrans.Text = "";
                Refresh();
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
        }
        
    }
}
